package games.eightPuzzle.heuristics;

import java.util.ArrayList;
import java.util.HashMap;

import games.eightPuzzle.states.*;

/**
 * @author avishl02
 * since the last move of a solution is to put the "hole" in its place
 * thus if one of the 4 possible neigbors of a hole is not inside it
 * we can add 2 more moves to the Manhattan Distances heuristic because
 * one of them will have to move to the hole one step befor the solution
 */
public class LastMoveHeuristic implements Heuristic{

	private ArrayList<Coordinate> _holes = null;
	private ArrayList<HashMap<Integer,Integer>> _holeNeighbors;
	
	/**
	 * ctor
	 * @param finalState
	 */
	public LastMoveHeuristic(SlidingPuzzleState finalState){
		_holes = finalState.getHolesList();
		_holeNeighbors = new ArrayList<HashMap<Integer,Integer>>();
		//calculate the holes neighbors
		for(int i=0;i<_holes.size();i++){
			Coordinate c = _holes.get(i);
			HashMap<Integer, Integer> tmp = new HashMap<Integer, Integer>();
			
			if (c.getI()>0){
				tmp.put(finalState.get(c.getI()-1, c.getJ()), null);
			}
			
			if (c.getI()<finalState.getNumRows()-1){
				tmp.put(finalState.get(c.getI()+1, c.getJ()), null);
			}
			
			if (c.getJ()>0){
				tmp.put(finalState.get(c.getI(), c.getJ()-1), null);
			}
			
			if (c.getJ()<finalState.getNumCols()-1){
				tmp.put(finalState.get(c.getI(), c.getJ()+1), null);
			}
			tmp.remove(0);
			_holeNeighbors.add(tmp);
		}
		
	}
	
	/* (non-Javadoc)
	 * @see ai.ex1.heuristics.Heuristic#rank(ai.ex1.SlidingPuzzleState)
	 */
	public int rank(SlidingPuzzleState state) {
		int total = 0;
		for(int i=0;i<_holes.size();i++){
			Coordinate c = _holes.get(i);
			int num = state.get(c.getI(), c.getJ());
			if (num!=0&&!_holeNeighbors.get(i).containsKey(num)){
				++total;
			}
		}
		return total;
	}


}
